package org.example.queue.blockingQueue;

import java.util.concurrent.*;

/**
 * Created by Administrator on 2018/6/14 0014.
 * 阻塞队列 测试类
 */
public class TestBlocking {
    public static void main(String[] args) {
        try {
            /**创建链式阻塞队列，并指定队列容量为10，注意当队列中元素个数达到10个时，使用put方法再次添加时则会阻塞
             * 普通的List即使设置了初始大小，超过容量时还是会自动改变容量；LinkedBlockingQueue 一旦指定了就不会改变容量了
             * */
            BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(10);

            /**因为会让main主线程等待消费者线程运行结束，所以这里使用倒计数锁存器，其同步个数与消费者个数一致*/
            CountDownLatch countDownLatch = new CountDownLatch(1);

            /**采用线程池方式
             * newCachedThreadPool：创建一个可缓存(大小可伸缩)线程池*/
            ExecutorService executorService = Executors.newCachedThreadPool();

            /** 阻塞队列是线程安全的，无论多少生产和消费者都是可行的，注意点如下：
             * 一个生产者、一个消费者时：生产者添加的元素都会被同一个消费者获取
             * 一个生产者、多个消费者时：生产者添加的元素会被多个消费者获取，如A获取了，则B、C等其它所有的就没有了
             * 多个生产者、多个消费者时：所有生产者添加的元素会放入同一个队列，而多个消费者则从队列中获取,队列中的元素被哪个消费者获取了之后，其余消费者就没有了
             * 生产者与消费者必须共享同一个阻塞队列 BlockingQueue
             */
            for (int i = 0; i < 2; i++) {
                if (i < 1) {
                    executorService.execute(new Producer(blockingQueue));//创建生产者线程
                } else {
                    executorService.execute(new Consumer(blockingQueue, countDownLatch));//创建消费者线程
                }
            }
            /**主线程开始阻塞，等待消费者消费完成
             * */
            countDownLatch.await();
            System.out.println("主线程开始关闭线程池，程序即将运行结束...");
            executorService.shutdown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
